package com.gin.no_gay_alliance.manager;

import android.util.Log;

import androidx.annotation.NonNull;

import com.fasterxml.jackson.core.type.TypeReference;
import com.gin.common.utils.FileIoUtils;
import com.gin.common.utils.FileUtils;
import com.gin.common.utils.TimeUtils;
import com.gin.jackson.utils.ObjectUtils;
import com.gin.nga.callback.JsonCallback;
import com.gin.nga.client.NgaClient;
import com.gin.nga.exception.NgaException;
import com.gin.nga.method.NukeApi;
import com.gin.nga.params.nuke.mission.MissionCheckInParam;
import com.gin.nga.params.nuke.mission.MissionListParam;
import com.gin.nga.response.body.nuke.MissionBody;
import com.gin.nga.response.body.nuke.MissionCheckInBody;
import com.gin.no_gay_alliance.app.MyApplication;
import com.gin.no_gay_alliance.callback.Callback;
import com.gin.no_gay_alliance.callback.RequestCallback;
import com.gin.no_gay_alliance.utils.DataStoreUtils;
import com.gin.no_gay_alliance.viewmodel.MissionModel;

import java.io.File;
import java.io.IOException;
import java.time.ZonedDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;

import okhttp3.Call;

/**
 * 任务管理器
 *
 * @author : ginstone
 * @version : v1.0.0
 * @since : 2023/9/12 23:25
 **/
public class MissionManager {
    private static final String TAG = MissionManager.class.getSimpleName();
    /**
     * 自动签到名单
     */
    private static final String DATA_STORE_KEY_AUTO_CHECK_IN = "AUTO_CHECK_IN";

    /**
     * 检查(完成)签到类任务
     *
     * @param missionId 任务id
     * @param callback  回调
     */
    public void missionCheckIn(long missionId, Callback<MissionCheckInBody> callback) {
        missionCheckIn(MyApplication.getClient(), missionId, callback);
    }

    /**
     * 检查(完成)签到类任务
     *
     * @param client    客户端
     * @param missionId 任务id
     * @param callback  回调
     */
    public void missionCheckIn(NgaClient client, long missionId, Callback<MissionCheckInBody> callback) {
        File cacheFile = getCacheFile(client.getUserId());

        MissionCheckInParam param = new MissionCheckInParam(missionId, true);
        NukeApi.missionCheckIn(client, param).async(new RequestCallback<MissionCheckInBody>(callback) {
            @Override
            public void onSuccess(MissionCheckInBody body) {
                if (cacheFile.exists() && cacheFile.delete()) {
                    Log.d(TAG, "删除缓存文件: " + cacheFile.getPath());
                }
                super.onSuccess(body);
            }
        });
    }

    /**
     * 开启当前用户的自动签到
     */
    public void addAutoCheckInUser() {
        addAutoCheckInUser(MyApplication.getClient().getUserId());
    }

    /**
     * 开启一个用户的自动签到
     *
     * @param userId 用户id
     */
    public void addAutoCheckInUser(long userId) {
        Set<Long> set = getAutoCheckInUsers();
        set.add(userId);
        setAutoCheckInUsers(set);
    }

    /**
     * 关闭当前用户的自动签到
     */
    public void removeAutoCheckInUser() {
        removeAutoCheckInUser(MyApplication.getClient().getUserId());
    }

    /**
     * 关闭一个用户的自动签到
     *
     * @param userId 用户id
     */
    public void removeAutoCheckInUser(long userId) {
        Set<Long> set = getAutoCheckInUsers();
        set.remove(userId);
        setAutoCheckInUsers(set);
    }

    /**
     * 自动完成签到类任务
     *
     * @param client 客户端
     */
    public void missionAutoCheckIn(NgaClient client) {
        Log.d(TAG, "自动签到: " + client.getUsername());
        missionList(false, client, data -> {
            for (MissionModel mission : data) {
                if (mission.checkAble != null && mission.checkAble) {
                    missionCheckIn(client, mission.id, res -> {
                        String message = !ObjectUtils.isEmpty(res.getMessage()) ? res.getMessage()
                                : String.format("%s 签到成功", mission.name);
                        MyApplication.app.handler.toast(client.getUsername() + ": " + message);
                    });
                }
            }
        });
    }

    /**
     * 查询任务列表
     *
     * @param ignoreCache 是否忽略缓存
     * @param callback    回调
     */
    public void missionList(boolean ignoreCache, @NonNull Callback<List<MissionModel>> callback) {
        missionList(ignoreCache, MyApplication.getClient(), callback);
    }

    /**
     * 查询任务列表
     *
     * @param ignoreCache 是否忽略缓存
     * @param client      客户端
     * @param callback    回调
     */
    public void missionList(boolean ignoreCache, NgaClient client, @NonNull Callback<List<MissionModel>> callback) {
        // 缓存文件
        File cacheFile = getCacheFile(client.getUserId());

        if (!ignoreCache && cacheFile.exists()) {
            try {
                callback.onSuccess(FileIoUtils.readObj(cacheFile, new TypeReference<List<MissionModel>>() {
                }));
                return;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        callback.beforeRequest();
        // 执行请求
        NukeApi.missionList(client, new MissionListParam()).async(new JsonCallback<MissionBody>() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                super.onFailure(call, e);
                callback.onFailure(call, e);
            }

            @Override
            public void onSuccess(MissionBody body) {
                List<MissionModel> missionModels = body.getData().stream().map(MissionModel::new).collect(Collectors.toList());
                try {
                    FileIoUtils.writeObj(cacheFile, missionModels);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                callback.onSuccess(missionModels);
            }

            @Override
            public void handleException(NgaException e) {
                super.handleException(e);
                callback.handleException(e);
            }
        });
    }

    /**
     * 查询任务列表(同步)
     *
     * @param ignoreCache 是否忽略缓存
     * @param client      客户端
     * @return
     */
    public List<MissionModel> missionList(boolean ignoreCache, NgaClient client) throws IOException {
        // 缓存文件
        File cacheFile = getCacheFile(client.getUserId());

        if (!ignoreCache && cacheFile.exists()) {
            return FileIoUtils.readObj(cacheFile, new TypeReference<List<MissionModel>>() {
            });
        }
        MissionBody missionBody = NukeApi.missionList(client, new MissionListParam()).sync();
        List<MissionModel> missionModels = missionBody.getData().stream().map(MissionModel::new).collect(Collectors.toList());
        FileIoUtils.writeObj(cacheFile, missionModels);
        return missionModels;
    }

    /**
     * 清空缓存
     */
    public static void clearCache() {
        try {
            FileUtils.deleteDir(getDir());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除一个指定用户的缓存
     *
     * @param userId 用户
     */
    public static void clearCache(long userId) {
        File cacheFile = getCacheFile(userId);
        if (cacheFile.exists() && cacheFile.delete()) {
            Log.d(TAG, "删除缓存文件: " + cacheFile.getPath());
        }
    }

    /**
     * 获取缓存文件, 每天一个
     *
     * @param userId 用户id
     * @return 缓存文件
     */
    @NonNull
    private static File getCacheFile(long userId) {
        return new File(getDir(), String.format(Locale.CHINA, "%d_%s.json", userId, TimeUtils.format(ZonedDateTime.now(), TimeUtils.DATE_FORMATTER)));
    }

    /**
     * 缓存目录
     *
     * @return 缓存目录
     */
    @NonNull
    private static File getDir() {
        return new File(MyApplication.app.getCacheDir(), "mission");
    }

    /**
     * 查询自动签到用户名单
     *
     * @return 自动签到用户名单
     */
    public Set<Long> getAutoCheckInUsers() {
        try {
            return DataStoreUtils.getInstance().get(DATA_STORE_KEY_AUTO_CHECK_IN, (Set<String>) new HashSet<String>()).stream().map(Long::parseLong).collect(Collectors.toSet());
        } catch (ClassCastException e) {
            DataStoreUtils.getInstance().remove(DATA_STORE_KEY_AUTO_CHECK_IN, new HashSet<>());
            e.printStackTrace();
            return new HashSet<>();
        }
    }

    public void setAutoCheckInUsers(Set<Long> set) {
        DataStoreUtils.getInstance().set(DATA_STORE_KEY_AUTO_CHECK_IN, set.stream().map(String::valueOf).collect(Collectors.toSet()));
    }

    /**
     * 当前用户是否在自动签到名单中
     *
     * @return 是否自动签到
     */
    public boolean isAutoCheckIn() {
        return getAutoCheckInUsers().contains(MyApplication.getClient().getUserId());
    }
}
